<?php

namespace Library;

use Library\Traits\HasInstance;


/**
 * @property array $config
 */
class App
{
    private static ?App $instance = null;
    protected array $config = [
        "version"=>LOW_CODE_VERSION,
        "name"=>"LowCode"
    ];
    protected array $iocMaps = [
        App::class,
        Request::class,
        Router::class
    ];
    protected Request $request;
    protected Router $router;
//    protected Logger $logger;
    protected string $moduleName = "app";
    protected string $controllerName = "admin";
    protected string $actionName = "index";

    use HasInstance;

    public function __construct() {
        $this->request = Request::make();
        $this->router = Router::make();
        $configPath = config_path("config.php");
        $config = require($configPath);
        $this->setConfig($config);
    }


    /**
     * @return void
     */
    protected function resolveRequest():void
    {
        $mapField = $this->config['mapField'];
        $pathInfo = $this->request->server("PATH_INFO");
        if ($pathInfo){
            $pathInfos = explode("/",$pathInfo);
            $this->moduleName = !empty($pathInfos[0])?$pathInfos[0]:"app";
            $this->controllerName = !empty($pathInfos[1])?$pathInfos[1]:"admin";
            $this->actionName = !empty($pathInfos[2])?$pathInfos[2]:"index";
        }else{
            $this->moduleName = $this->request->get($mapField["moduleField"],"app");
            $this->controllerName = $this->request->get($mapField["controllerField"],"admin");
            $this->actionName = $this->request->get($mapField["actionField"],"index");
        }
    }


    /**
     * @return string
     */
    public function getControllerClass():string
    {
        $moduleName = ucfirst($this->moduleName);
        $controllerName = ucfirst($this->controllerName);
        if ($moduleName=="App"){
            $format = "\\%s\\Controllers\\%s";
        }else{
            $format = "\\Modules\\%s\\Controllers\\%s";
        }
        return sprintf($format, $moduleName, $controllerName);
    }

    /**
     * @return Ioc
     */
    public function run():Ioc
    {
        $this->resolveRequest();
        return Ioc::run($this);
    }

    /**
     * @return string
     */
    public function getModuleName(): string
    {
        return $this->moduleName;
    }

    /**
     * @return string
     */
    public function getController(): string
    {
        return $this->controllerName;
    }

    /**
     * @return string
     */
    public function getActionName(): string
    {
        return $this->actionName;
    }

    /**
     * @param array $config
     * @return $this
     */
    public function setConfig(array $config): static
    {
        $this->config = array_merge($this->config,$config);
        $this->resolveRequest();
        return $this;
    }

    /**
     * @param string $key
     * @return mixed
     */
    public function getConfig(string $key = ""): mixed
    {
        return $key?$this->config[$key]:$this->config;
    }

    /**
     * @return Request
     */
    public function getRequest(): Request
    {
        return $this->request;
    }

    /**
     * @return Router
     */
    public function getRouter(): Router
    {
        return $this->router;
    }

    private function __clone() {}

}